<?php
/**
 * Nweb Editor
 *
 * This script is protected by copyright. Its use, copying, modification
 * and distribution without written consent of the author is prohibited.
 *
 * @category    source
 * @package     pl.nweb.editor.autoloader
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt  GNU Lesser General Public
 * @version     1.0 $Id$
 * @link        https://nweb-editor.googlecode.com
 * @link        http://editor.nweb.pl
 */

namespace pl\nweb\editor\autoloader;

/** \pl\nweb\editor\autoloader\Exception */
require_once __DIR__ . '/exception.php';

/**
 * Autoloader
 *
 * @category    source
 * @package     pl.nweb.editor.autoloader
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @version     1.0 $Id$
 */
class Autoloader
{
    /**
     * Status rejestracji autoloadera
     *
     * @var boolean
     */
    private static $_registered = false;

    /**
     * Źródła
     *
     * @var string
     */
    private static $_src = null;

    /**
     * Przestrzeń nazw aplikacji
     *
     * @var string
     */
    private static $_namespaces = array();

    /**
     * Definiuje katalog źródeł
     *
     * @param  string $dir katalog źródeł
     * @return void
     * @throws \pl\nweb\editor\autoloader\Exception
     */
    public static function setSourceDir ($dir)
    {
        if($path = realpath($dir)) {
            self::$_src = $path;
        } else {
           throw new Exception ('source dir "' . $dir . '" not exists', Exception::EX_CODE_SRC_NOT_EXISTS);
        }
    }

    /**
     * Zwraca katalog źródeł
     *
     * @return string
     */
    public static function getSourceDir ()
    {
        if(null === self::$_src) {
           throw new Exception ('source dir not defined', Exception::EX_CODE_SRC_NOT_DEFINED);
        }
        return self::$_src;
    }

    /**
     * Definiowanie przestrzeni nazw
     *
     * @return string
     */
    public static function addNamespace ($namespace, $dir)
    {
        self::$_namespaces[] = array(
            $namespace,
            $dir,
            strlen($namespace)
        );
    }

    /**
     * Autoładowanie klasy
     *
     * @param  string $class nazwa klasy
     * @return boolean
     */
    public static function loadClass ($class)
    {
        if(class_exists($class, false) || interface_exists($class, false)) {
            return true;
        }

        $file = str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php';
        if(self::_find(self::getSourceDir() . DIRECTORY_SEPARATOR . $file)) {
            return true;
        }

        foreach (self::$_namespaces as $namespace) {
            if(substr($class, 0, $namespace[2]) == $namespace[0]) {
                if(self::_find($namespace[1] . DIRECTORY_SEPARATOR  . $file)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Próba znalezienia pliku
     *
     * @param string $class
     * @param string $path
     * @return boolean
     */
    private static function _find ($path)
    {
        if(is_file($path)) {
            include_once $path;
            return true;
        }
        return false;
    }

    /**
     * Rejestracja autoloadera
     *
     * @return void
     */
    public static function register ()
    {
        if(false === self::$_registered) {
            self::$_registered = spl_autoload_register(
                __NAMESPACE__ . '\Autoloader::loadClass',
                true,
                true
            );
        }
    }
}